package model

import (
	"DomCtrlCenter/network"
	"encoding/json"
	"fmt"
	"net"
	"net/http"
	"strconv"
	"strings"
	"time"
)

var AirAddr *net.UDPAddr = nil
var AirOnline bool = false
var AirLastRecvTime time.Time
var Temperature float64
var Humidity int
var SetTemperature int = 26
var SetFanSpeed int = 0
var SetAirPower bool = false
var SendQueue chan string
var SendComplete bool = true
var TimerOn bool = false
var Timer <-chan time.Time
var ToAck = ""

func AirRun() {
	AirConfigInit()
	SendQueue = make(chan string, 32)
	go network.UDPListen(func(conn *net.UDPConn, addr *net.UDPAddr, msg string) {
		AirLastRecvTime = time.Now()
		if msg[0] == '<' && msg[1] == '0' {
			AirAddr = addr
			fmt.Sscanf(string(msg[2:4])+"."+string(msg[4]), "%f", &Temperature)
			fmt.Sscanf(string(msg[5:7]), "%d", &Humidity)
			fmt.Printf("收到温度控制模块发来的实时温湿度：%.1f℃ , %d%%\n来源:%s\n", Temperature, Humidity, addr.String())
		} else if msg[0] == '(' {
			if len(ToAck) != 0 {
				if ToAck == msg {
					ToAck = ""
				}
			}
		}
	})
	go func() { //处理发送队列的线程
		for {
			msg := <-SendQueue
			SendComplete = false
			for i := 0; i < 3; i++ {
				network.UDPSend(AirAddr, msg)
				ToAck = msg[1 : len(msg)-1]
				time.Sleep(2 * time.Second)
				if len(ToAck) == 0 {
					break //如果两秒没收到回复就重发
				}
				fmt.Printf("发送失败'%s',第%d次重发\n", msg, i)
			}
			fmt.Printf("成功发送'%s',当前消息队列长度:%d\n", msg, len(SendQueue))
			if len(SendQueue) == 0 {
				SendComplete = true
			}
		}
	}()
	tick := time.Tick(time.Second)
	for { //在线状态更新
		select {
		case <-tick:
			if time.Now().Sub(AirLastRecvTime) > time.Second*20 {
				AirOnline = false
			} else {
				AirOnline = true
			}
		}
	}
}
func ScheduleTimerExecute(t <-chan time.Time, power bool, done chan struct{}) {
	for {
		select {
		case <-t:
			if !TimerOn {
				return
			}
			if power {
				SetAircon(SetTemperature, SetFanSpeed)
			} else {
				ShutdownAircon()
			}
			t = time.After(time.Hour * 24) // 创建一个新的定时器
		case <-done:
			return
		}
	}
}
func IsAirFree() bool {
	return SendComplete
}

func IsAirModelOnline() bool {
	return AirOnline
}

func SetAircon(temperature, fanSpeed int) {
	if AirAddr == nil {
		return
	}
	SetTemperature = temperature
	SetFanSpeed = fanSpeed
	SetAirPower = true
	AirConfig.KeyValueMap["SetTemperature"] = strconv.Itoa(temperature)
	AirConfig.KeyValueMap["SetFan"] = strconv.Itoa(fanSpeed)
	AirConfig.KeyValueMap["SetPower"] = "1"
	AirConfig.SerializeToFile()
	SendQueue <- fmt.Sprintf("<(1%2d%1d)>", temperature, fanSpeed)
}

func ShutdownAircon() {
	if AirAddr == nil {
		return
	}
	SetAirPower = false
	AirConfig.KeyValueMap["SetPower"] = "0"
	AirConfig.SerializeToFile()
	SendQueue <- "<(0)>"
}

type AirStatus struct {
	AirOnline      int
	Temperature    float64
	Humidity       int
	SetTemperature int
	SetFanSpeed    int
	SetAirPower    string
	Time           string
	TimerOn        int
	TimerJson      string
}

func AirGetStatus() AirStatus {
	var airOnline int
	var setAirPower string
	var timerOn int
	if SetAirPower {
		setAirPower = "已开机"
	} else {
		setAirPower = "已关机"
	}
	if TimerOn {
		timerOn = 1
	} else {
		timerOn = 0
	}
	if IsAirModelOnline() {
		airOnline = 1
	} else {
		airOnline = 0
	}
	timerJson, _ := AirConfig.KeyValueMap["TimerJson"]
	return AirStatus{airOnline, Temperature, Humidity, SetTemperature, SetFanSpeed, setAirPower, AirLastRecvTime.Format("2006-01-02 15:04:05"), timerOn, timerJson}
}

func HandleSetAirconRequest(writer http.ResponseWriter, request *http.Request) {
	ok := true
	err := request.ParseForm()
	if err != nil {
		ok = false
	}
	t, err := strconv.Atoi(request.FormValue("t"))
	if err != nil {
		ok = false
	}
	f, err := strconv.Atoi(request.FormValue("f"))
	if err != nil {
		ok = false
	}
	p, err := strconv.Atoi(request.FormValue("p"))
	if err != nil {
		ok = false
	}
	if !ok {
		writer.WriteHeader(http.StatusBadRequest)
		writer.Write([]byte("Bad Request"))
		return
	}
	if p == 0 {
		ShutdownAircon()
		fmt.Println("正在关闭空调")
	} else {
		SetAircon(t, f)
		fmt.Printf("正在设置空调为：%d℃ ，%d风力\n", t, f)
	}
	writer.Write([]byte("OK"))
}

func HandleSetAirconTimerRequest(writer http.ResponseWriter, request *http.Request) {
	var data TimerSetData
	err := json.NewDecoder(request.Body).Decode(&data)
	if err != nil {
		http.Error(writer, "Bad request", http.StatusBadRequest)
		return
	}
	fmt.Println(data)
	if data.IsTimerOn == 1 {
		TimerData = data
		StartAllTimer()
		jsonData, _ := json.Marshal(data)
		AirConfig.KeyValueMap["TimerJson"] = string(jsonData)
		AirConfig.KeyValueMap["TimerOn"] = "1"
		AirConfig.SerializeToFile()
	} else {
		TimerOn = false
		AirConfig.KeyValueMap["TimerOn"] = "0"
		AirConfig.SerializeToFile()
		for _, v := range TimerForceDone {
			v <- struct{}{}
			TimerForceDone = make([]chan struct{}, 0)
		}
	}
}

func StartAllTimer() {
	TimerOn = true
	for _, v := range TimerData.Ons {
		SetTimerByString(v, true)
	}
	for _, v := range TimerData.Offs {
		SetTimerByString(v, false)
	}
}

func SetTimerByString(str string, power bool) {
	var hour, minute int
	var err error
	parts := strings.SplitN(str, ":", 2) // 2 表示我们只需要分割为最多两部分
	if len(parts) == 2 {
		hour, err = strconv.Atoi(parts[0])
		if err != nil {
			fmt.Println("解析定时器时出现错误4")
		}
		minute, err = strconv.Atoi(parts[1])
		if err != nil {
			fmt.Println("解析定时器时出现错误5")
		}
		now := time.Now()
		year, month, day := now.Year(), now.Month(), now.Day()
		// 生成时间对象
		t := time.Date(year, month, day, hour, minute, 0, 0, time.Local)
		var openOrClose string
		if power {
			openOrClose = "开启"
		} else {
			openOrClose = "关闭"
		}
		if t.After(now) {
			fmt.Println("将在" + t.Sub(now).String() + "后" + openOrClose + "空调")
			TimerForceDone = append(TimerForceDone, make(chan struct{}))
			go ScheduleTimerExecute(time.After(t.Sub(now)), power, TimerForceDone[len(TimerForceDone)-1])
		} else {
			fmt.Println("将在" + (time.Hour*24 - now.Sub(t)).String() + "后" + openOrClose + "空调")
			TimerForceDone = append(TimerForceDone, make(chan struct{}))
			go ScheduleTimerExecute(time.After(time.Hour*24-now.Sub(t)), power, TimerForceDone[len(TimerForceDone)-1])
		}
	} else {
		// 处理没有找到 ":" 的情况
		fmt.Println("解析定时器时出现错误3")
	}
}
